#include "transContentPortMgr.hpp"

TransContentPortMgr* TransContentPortMgr::_instance = NULL;


TransContentPortMgr* TransContentPortMgr::getInstance(){
	if(_instance == NULL){
		_instance = new TransContentPortMgr();
		if(_instance->getState() != INS_STATE_OK){
			releaseInstance();
		}
	}
	return _instance;
}

void TransContentPortMgr::releaseInstance(){
	debug_enter();
	if(_instance != NULL){
		delete _instance;
		_instance = NULL;
	}
	debug_leave();
}

int TransContentPortMgr::getPortCapacity(){
	return mPortCapacity;
}

int TransContentPortMgr::getPortCount(){
	return mPortCount;
}

//class state
int TransContentPortMgr::getState(){
	return mState;
}

void TransContentPortMgr::onTimer(){
	log_info("port manager==> on timer!!");
	debug_enter();
	transContentIRemove* ins;
	for(int i=0, count=0; i<mPortCapacity && count<mPortCount; ++i){
		if(portList[i].localPort != 0){
			++count;
			if(portList[i].instance != NULL){
				ins = (transContentIRemove*)portList[i].instance;
				if(ins->canRemoved() == 1){
					removePortRecord(-1, i);
				}
			}
		}
	}
	debug_leave();
	return;
}

TransContentPortMgr::TransContentPortMgr(){
	mPortCapacity = TransContentSetting::getAllPortCount();
	mPortCount = 0;
	mState = INS_STATE_ERROR;
	portList = (portElement*)calloc(mPortCapacity, sizeof(portElement));
	if(portList == NULL){
		logd_error("alloc memory for port manager failed: %s", strerror(errno));
		return;
	}
	pthread_mutex_init(&mutex_port, NULL);
	mState = INS_STATE_OK;
}

/////////////////////////////////////////////////////////////////////////
/// destructor to dispose all records
/////////////////////////////////////////////////////////////////////////
TransContentPortMgr::~TransContentPortMgr(){
	mState = INS_STATE_ERROR;
	if(portList != NULL){
		destroyAllPortRecord();
		free(portList);
	}
	pthread_mutex_destroy(&mutex_port);
}

/////////////////////////////////////////////////////////////
/// check target port whether exist
/// 
/// parameters:
///		port: the target port to check
///		portState: the port with special state, default is error
///
/// return:
///		index: the port record index, when port exist and state is equal
///		E_TRANC_PortNotExist, when port not exist
///		E_TRANC_PortAlreadyExist: port exist, but state not equal
//////////////////////////////////////////////////////////////
int TransContentPortMgr::isPortExist(int port, int portState){
	int result = 0;
//	pthread_mutex_lock(&mutex_port);
	for(int i=0; i< mPortCapacity; ++i){
		/// portState <=0, when the port state <=0, will not compare the port state, else will compare
		if(portList[i].localPort == port){
			result = E_TRANC_PortAlreadyExist;
			if(portState <= 0 || portList[i].portState == portState){
				result = i;
				goto End:
			}
		}
	}
	result = E_TRANC_PortNotExist;
End:
//	pthread_mutex_unlock(&mutex_port);
	log_info("port manager, isPort exist, port=%d, state=%d, result is=%d", port, portState, result);
	return result;
}

/////////////////////////////////////////////
/// add a port element to port record list
/// 
/// parameter:
///		element: the port record to add
///
/// return:
///		index: the add index
///		E_TRANC_BufferTooSmall: buffer overflow, no more space to hold the record
/////////////////////////////////////////////
int TransContentPortMgr::AddPortRecord(const portElement* element){
	int index=0;
	int result = 0;
	pthread_mutex_lock(&mutex_port);
	/// in all record space
	logd_info("start to look up all records");
	for(; index< mPortCount; ++index){
		/// find first local port == 0 index
		if(portList[index].localPort == 0){
			logd_info("get an empty record, index=%d", index);
			goto Sucess;
		}
	}
	logd_info("port manager, look up all reocrds already, but can not find an empty one, will increase the buffer size");
	if(increasePortRecordSpace() != E_TRANC_SUCESS){
		logd_error("port manager, increase the port list space failed.");
		goto Failed;
	}

Sucess:
	portList[index] = *element;
	++mPortCount;
	logd_info("port manager, add port manager record sucess, at: %d", index);
	result = index;
	goto End;

Failed:
	logd_error("add port manager record failed, no more buffer");
	result = E_TRANC_BufferTooSmall;

End:
	pthread_mutex_unlock(&mutex_port);

	return result;
}

//////////////////////////////////////////////////////////////
/// add a port to record, the port state is registing, and create a new regist instance for it
///
/// parameters:
///		port: the port to add
///
/// return:
///		index: the add index
///		E_TRANC_BufferTooSmall: buffer overflow, no more space to hold the record
///////////////////////////////////////////////////////////////
int TransContentPortMgr::addPortRecordAsRegist(int port){
	int result = 0;
	debug_enter();
	portElement _tempRecord;
	_tempRecord.localPort = port;
	_tempRecord.portState = PORT_STATE_REGISTING;
	_tempRecord.romoveCallback = NULL;
	_tempRecord.instance = new TransContentPortRegist();

	logd_info("add port, port as regist record to port list");
	result = AddPortRecord(&_tempRecord);
	if(result == E_TRANC_BufferTooSmall){
		logd_error("add port as regsit record failed, no more space to hold it");
		delete _tempRecord.instance;
	}
	debug_leave();
	return result;	
}

///////////////////////////////////////////////
/// get a already registed port, so that can avoid the stack create fifo and open it again
/// 
/// return:
///		-1: no port registed
///		port: the registed port
///////////////////////////////////////////////
int TransContentPortMgr::getRegistedPort(){
	debug_enter();
	int index=0;
	while(index < mPortCapacity){
		if(portList[index].localPort != 0){
			logd_info("get a regsited port, at index=%d", index);
			return portList[index].localPort;
		}
		++index;
	}
	logd_error("get a regsited port, failed, no registed port, will return -1");
	return -1;
}

//////////////////////////////////////////////////////////////////////////////////
/// vroute instance call this method to get a port and return the port record index
///
/// parameters:
///		port: the bind port
///		timeout: wait max seconds
///		bscb: the bind callback
/// return:
///		E_TRANC_InsStateFailed: the port manager instance state invalidate
///		E_TRANC_ParamError: the bind port value <= 0
///		E_TRANC_PortAlreadyExist: the bind port already exist in the port list
///		E_TRANC_BufferTooSmall: the port manager have no space to add the regist record
///		E_TRANC_TIMEOUT: the bind method wait timeout
///		E_TRANC_NONBLOCK: bind method use sync style
///		E_TRANC_OpeartionNotInvalidate: port state can not changed to reigsted
///		vroute_t: the regist record index value
//////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::bind(int port){
	int index = 0;
	int result = 0;
	debug_enter();

	/// check state
	if(mState == INS_STATE_ERROR){
		log_error("bind, call bind method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}

	/// check parameer
	if(port < 0){
		logd_error("bind method parameter: port=%d, invalidate", port);
		return E_TRANC_ParamError;
	}

	result = isPortExist(port, PORT_STATE_REGISTED);
	if(result > 0){
		logd_info("bind, port =%d, already exist, and state is registed, so just return this index=%d", port, result);
		return result;
	}else if(result == E_TRANC_PortAlreadyExist){
		logd_info("bind, port = %d, exist already, check the port state can be changed to registed", port);
		if(canChagnePortStateToRegisted(port) == 0){
			logd_info("bind, port = %d, exist already, but can not changed state to registed", port);
			return E_TRANC_OpeartionNotInvalidate;
		}
		return addPortRecordAsRegist(port);
	}else{
		logd_info("bind, port = %d, not exist, regist a new record, return as vid", port);
		return registPortInner(port, REGIST_PORT_TYPE_APPLY, REGIST_RETURN_VID);
	}
}

////////////////////////////////////////////////////////////////////////////
/// set the port state to listen, and create the listen instance
/// must call this method before accept
///
/// parameters:
///		vid: the vroute_t to listen
///		count: the max listen count
///
/// return:
///		E_TRANC_InsStateFailed: the port manager instance state invalidate
///		E_TRANC_ParamError: the parameter: count or vid out of range. or the vid's port invalidate
///		E_TRANC_OpeartionNotInvalidate: the port state int registed
///		E_TRANC_SystemError: create new instance failed
///		E_TRANC_SUCESS: listen sucessfully
//////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::listen(vroute_t vid, int count){
	TransContentPortListen* listenIns = NULL;
	if(mState == INS_STATE_ERROR){
		log_error("call listen method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	if(count < 1 || count > LISTEN_COUNT_MAX){
		log_error("listen method parameter, count=%d,out of range", count);
		return E_TRANC_ParamError;
	}
	if( vid < 0 || vid > this->mPortCapacity){
		log_error("listen method parameter, vid=%d, out of range", vid);
		return E_TRANC_ParamError;		
	}
	if(portList[vid].localPort == 0){
		log_error("listen method parameter, vid=%d's localPort==0", vid);
		return E_TRANC_ParamError;
	}
	if(portList[vid].portState != PORT_STATE_REGISTED){
		log_error("port state is:%d, can not call listen", portList[vid].portState);
		return E_TRANC_OpeartionNotInvalidate;
	}
	/// remove the regist instance
	if(portList[vid].instance != NULL){
		delete portList[vid].instance;
		portList[vid].instance = NULL;
	}
	listenIns = new TransContentPortListen();
	if(listenIns == NULL){
		logd_fata_error("create instance of port listen failed, %s!!", strerror(errno));
		return E_TRANC_SystemError;
	}
	listenIns.listen(count);
	log_info("change port list id=%d, instance to listen", vid);
	portList[vid].instance = listenIns;
	portList[vid].portState = PORT_STATE_LISTEN;
	return E_TRANC_SUCESS;
}

////////////////////////////////////////////////////////////////////////////////////
/// accept connection from remote devices, must call this method to receive connection from other deivces 
/// or local other port commulicate use stream style
///
/// parameters:
///		vid: the vroute index to accept, the value must get from bind or convert from port
///		timeout: the max time to wait
///		ascb: the accept callback
///
/// return:
///		E_TRANC_InsStateFailed: the port manager instance state invalidate
///		E_TRANC_ParamError: the parameter: count or vid out of range. or the vid's port invalidate
///		E_TRANC_OpeartionNotInvalidate: the port state int registed
///		E_TRANC_InnerLogicError: the accept instance is null
///		E_TRANC_ACCEPT_FULL: the accept count reached the max limits
///		E_TRANC_TIMEOUT: the accept method wait timeout
///		E_TRANC_NONBLOCK: the accept method use sync style
///		vroute_t: the accepted new  record index value
////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::accept(vroute_t vid, int timeout, acceptSyncCallback ascb){
	int result;
	if(mState == INS_STATE_ERROR){
		log_error("call accept method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	if( vid < 0 || vid > this->mPortCapacity){
		log_error("accept method parameter, vid=%d, out of range", vid);
		return E_TRANC_ParamError;		
	}
	if(portList[vid].localPort == 0){
		log_error("accept method parameter, vid=%d's localPort==0", vid);
		return E_TRANC_ParamError;
	}
	if(portList[vid].instance == NULL){
		log_error("accept port reocrd, but the instance is NULL");
		return E_TRANC_InnerLogicError;
	}
	/// may be not the first time call accept, so the state may be accepting or acceptfull
	/// if accepting, test whether full fist, then accept if not full or return
	/// if acceptfull, just return
	if(portList[vid].portState != PORT_STATE_LISTEN){
		if(portList[vid].portState != PORT_STATE_ACCEPTING && portList[vid].portState != PORT_STATE_ACCEPT_FULL){
			log_error("port state is:%d, can not call accept", portList[vid].portState);
			return E_TRANC_OpeartionNotInvalidate;
		}
		if(portList[vid].portState == PORT_STATE_ACCEPTING &&((TransContentPortListen*)(portList[vid].instance))->isAcceptFull()==1){
			portList[vid].portState = PORT_STATE_ACCEPT_FULL;
			return E_TRANC_ACCEPT_FULL;
		}else if(portList[vid].portState == PORT_STATE_ACCEPT_FULL){
			return E_TRANC_ACCEPT_FULL;
		}
	}else{
		portList[vid].portState = PORT_STATE_ACCEPTING;
	}
	if(timeout <= 0){		
		logd_info("accept method use timeout=%d, will cover to :%d", timeout, INT_MAX);
		timeout = INT_MAX;
	}

	((TransContentPortListen*)(portList[vid].instance))->setTimeout(timeout);
	((TransContentPortListen*)(portList[vid].instance))->setCallback(ascb);
	log_info("port manager==> accept: starting call listen port instance to accept");
	return ((TransContentPortListen*)(portList[vid].instance))->accept();
}

/////////////////////////////////////////////////////////////////////////////////////////////////
/// receive data from remote devices, use stream style
///
/// parameters:
///		vid: the receive port index in the port list
///		flag: set the receive method not block, if no data avaliable, just return
///		buffer: the buffer to store data from remote devices or local device other port
///		bufferLen: the buffer length
///		timeout: the receive wait max time in seconds
///		rscb: the receive callback method
///
/// return:
///		E_TRANC_InsStateFailed: the port manager instance state invalidate
///		E_TRANC_ParamError: the parameter invalidate
///		E_TRANC_OpeartionNotInvalidate: the port state int registed
///		E_TRANC_InnerLogicError: the accept instance is null
///		E_TRANC_TIMEOUT: the accept method wait timeout
///		E_TRANC_NONBLOCK: the accept method use sync style
///		length: the received data length
/////////////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::receive(vroute_t vid, int flag, void* buffer, int bufferLen, int timeout, recvSyncCallback rscb){
	if(mState == INS_STATE_ERROR){
		log_error("call receive method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	if( vid < 0 || vid > this->mPortCapacity){
		log_error("receive method parameter, vid=%d, out of range", vid);
		return E_TRANC_ParamError;		
	}
	if(portList[vid].localPort == 0){
		log_error("receive method parameter, vid=%d's localPort==0", vid);
		return E_TRANC_ParamError;
	}
	if(portList[vid].instance == NULL){
		log_error("receive port reocrd, but the instance is NULL");
		return E_TRANC_InnerLogicError;
	}
	if(portList[vid].portState != PORT_STATE_STREAM){
		log_error("port state is:%d, can not call receive", portList[vid].portState);
		return E_TRANC_OpeartionNotInvalidate;
	}
	if(timeout <= 0){		
		logd_info("receive method use timeout=%d, will cover to :%d", timeout, INT_MAX);
		timeout = INT_MAX;
	}
	if(flag != 0 && flag != RECEIVE_FLAG_NONBLOCK){
		log_error("receive method parameter, flag=%d out of range", flag);
		return E_TRANC_ParamError;
	}
	if(buffer == NULL || bufferLen <= 0){
		log_error("receive method parameter, buffer is NULL or bufferLen <= 0");
		return E_TRANC_ParamError;
	}
	log_info("call stream port instance receive instance's receive method");
	return ((TransContentPortStream*)(portList[vid].instance))->receive(flag, buffer, bufferLen, timeout, rscb);
}

//////////////////////////////////////////////////////////////////////////////////////////////
/// send data to remote port use local port, the port get from vid
///
/// parameters:
///		vid: the port index in port list to use to send
///		flag: must be 0 or SEND_FLAG_NONBLICK, to set non block when buffer not avaliable
///		buffer: the data to send out
///		bufferLen: the data length
///		timeout: the max wait timeout second
///		sscb: the send callback
///
/// return:
///		E_TRANC_InsStateFailed: the port manager instance state invalidate
///		E_TRANC_ParamError: the parameter invalidate
///		E_TRANC_OpeartionNotInvalidate: the port state int registed
///		E_TRANC_InnerLogicError: the accept instance is null
///		E_TRANC_TIMEOUT: the accept method wait timeout
///		E_TRANC_NONBLOCK: the accept method use sync style
///		length: the send data length
/////////////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::send(vroute_t vid, int flag, const void* buffer, int bufferLen, int timeout, sendSyncCallback sscb){
	if(mState == INS_STATE_ERROR){
		log_error("call send method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	if( vid < 0 || vid > this->mPortCapacity){
		log_error("send method parameter, vid=%d, out of range", vid);
		return E_TRANC_ParamError;		
	}
	if(portList[vid].localPort == 0){
		log_error("send method parameter, vid=%d's localPort==0", vid);
		return E_TRANC_ParamError;
	}
	if(portList[vid].instance == NULL){
		log_error("send port reocrd, but the instance is NULL");
		return E_TRANC_InnerLogicError;
	}
	if(portList[vid].portState != PORT_STATE_STREAM){
		log_error("port state is:%d, can not call send", portList[vid].portState);
		return E_TRANC_OpeartionNotInvalidate;
	}
	if(timeout <= 0){		
		logd_info("send method use timeout=%d, will cover to :%d", timeout, INT_MAX);
		timeout = INT_MAX;
	}
	if(flag != 0 && flag != SEND_FLAG_NONBLICK){
		log_error("send method parameter, flag=%d out of range", flag);
		return E_TRANC_ParamError;
	}
	if(buffer == NULL || bufferLen <= 0){
		log_error("send method parameter, buffer is NULL or bufferLen <= 0");
		return E_TRANC_ParamError;
	}
	log_info("call stream port instance send instance's send method");
	return ((TransContentPortStream*)(portList[vid].instance))->send(flag, buffer, bufferLen, timeout, rscb);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
/// send a buffer content to target, use flag set path, but path will at virutal connect layer, so the flat will be send to virual connect layer dierctly
/// the localPort can be not exist or invaliate or exist already, the flag will set how to set deal for each caes
///
/// parameters:
///		localPort: use the port to send Content, the port can be exist already, or not, or a invlidate poort
///		target: the content will be send to where, set the remote address and port
///		flag: the path flag, the send flag
///		buffer: the buffer where data in it
///		bufferLen: the buffer data length
///		timeout: no use
///		sendToSyncCallback: no use
///	return:
//		E_TRANC_InsStateFailed: instance state error
//		E_TRANC_ParamError: parameters error
//		E_TRANC_TIMEOUT: no use
//		E_TRANC_PortNotExist: the localPort not exist and the flag not allow to create it
//		E_TRANC_PortAlreadyExist:: the localPort already exist and can not be use as record, the flag not allowd to create a new one
//		length: send data length
//////////////////////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::sendTo(int localPort, const EndPoint* target, int flag, const void* buffer, int bufferLen, int timeout, sendToSyncCallback stscb){
	int index = 0;
	int result = 0;
	portElement element;
	TransContentPortRecord* recordIns = NULL;
	if(mState == INS_STATE_ERROR){
		log_error("call sendTo method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	if(target->addr.serial_id <0 || target->port <= 0){
		log_error("sendTo method parameter, target.addr=%lld; port=%d", target->addr.serial_id, target->port);
		return E_TRANC_ParamError;
	}
	if(flag != 0 && flag != SEND_FLAG_NONBLICK && flag != SEND_FLAG_USE_FIXEDPATH && flag != RECORD_DATA_FLAG_CREATE_PORT){
		log_error("sendTo method parameter, flag=%d out of range", flag);
		return E_TRANC_ParamError;
	}
	if(buffer == NULL || bufferLen <= 0){
		log_error("sendTo method parameter, buffer is NULL or bufferLen <= 0");
		return E_TRANC_ParamError;
	}
	if(localPort <= 0){
		index = registPortInner(localPort, REGIST_PORT_TYPE_GET, REGIST_RETURN_VID);
		changeRecordState(index, PORT_STATE_REGISTED, PORT_STATE_PACKET, recordIns);
		goto SendData;
	}
	/// 1. check the port with the record state exist
	///		1.1 exist
	///			goto sendData
	///		1.2 no exist
	///			1.2.1 check port exist and can used to as record
	///				1.2.1.1 port not exist
	///					regist this port, then goto sendData
	///				1.2.1.2 can
	///					create a new record with record then goto sendData
	///				1.2.1.3 port not
	///					1.2.1.3.1 flag is createNew
	///						1.2.3.1.1 is get a port, then goto sendData
	///						1.2.3.1.2 is not, return port exist
	///
	///check the port exist already and used as packet protocol
	index = isPortExist(localPort, PORT_STATE_PACKET);
	if(index > 0){
		logd_info("sendTo, port:%d exist with port state packet, just goto senddata", localPort);
		goto SendData;
	}else if(index == E_TRANC_PortAlreadyExist){
		logd_info("sendTo, port:%d exist, but port state not packet, check state is registed", localPort);
		index = isPortExist(localPort, PORT_STATE_REGISTED);
		if(index > 0){
			logd_info("sendTo, port:%d exist, and port state is registed, just change the port state", localPort);
			changeRecordState(index, PORT_STATE_REGISTED, PORT_STATE_PACKET, recordIns);
			goto SendData;
		}
		logd_info("sendTo, port:%d exist, but state is not registed or packet, should check can be used as packet", localPort);
		if(canChangePortStateToRecord(localPort)){
			logd_info("sendTo, port:%d, exist, and it's state can be used as packet, now just create a port as packet");
			element.localPort = localPort;
			element.portState = PORT_STATE_PACKET;
			recordIns = new TransContentPortRecord();
			element.instance = recordIns;
			index = AddPortRecord(&element);
			if(index == E_TRANC_BufferTooSmall){
				/// no space to hold the record
				delete element.instance;
				return index;
			}
			//insert sucessfully
			goto SendData;

		}else{
			logd_error("sendTo, port: %d, exist, but can not be used as packet", localPort);
			return E_TRANC_OpeartionNotInvalidate;
		}
	}else{
		//port not exist yet
		logd_info("sendTo, port:%d, not exist, check flag to create", localPort);
		if(flag & RECORD_DATA_FLAG_CREATE_PORT){
			//regsit a port then change the state
			index = registPortInner(localPort, REGIST_PORT_TYPE_APPLY, REGIST_RETURN_VID);
			if(index > 0){
				logd_info("sendTo, regist port finished");
				recordIns = new TransContentPortRecord();
				//after regsit the port state is registed, so changed it
				changeRecordState(index, PORT_STATE_REGISTED, PORT_STATE_PACKET, recordIns);
				goto SendData;
			}else{
				logd_error("sendTo, regist port finised, error, the port must be existd");
				return E_TRANC_PortAlreadyExist;
			}
		}
		logd_error("sendTo, the port:%d, not exist, and flag not set to create a new record! just return error", localPort);
		return E_TRANC_PortNotExist;
	}

SendData:
	if(timeout <= 0){		
		logd_info("sendTo method use timeout=%d, will cover to :%d", timeout, INT_MAX);
		timeout = INT_MAX;
	}
	log_info("call stream port instance sendTo instance's sendTo method");
	return ((TransContentPortRecord*)(portList[index].instance))->sendTo(target, flag, buffer, bufferLen, timeout, stscb);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// receive data from local port, the localPort must exist already, and the port can be used as packet
/// after return set the data into the buffer and return the recievd length
///
/// paramenters:
///		localPort: the receive data port, the port must be validate.
///		flag: the flag to receive data
///		buffer: the buffer to store the data
///		bufferLen: the buffer length
///		timeout: the recieve data max wait timeout
///		rfscb: receive data callback
///	return:
///		E_TRANC_NO_DATA_AVALIABLE: no data avaliable on this port
///		E_TRANC_InsStateFailed: the port manager istance state error
///		E_TRANC_ParamError: the parameters for this method error
///		E_TRANC_TIMEOUT: the method timeout
///		length: the recived data length
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::receiveFrom(int localPort, int flag, void* buffer, int bufferLen, int timeout, receiveFromSyncCallback rfscb){
	int index = 0;
	portElement element;
	TransContentPortRecord* recordIns = NULL;
	if(mState == INS_STATE_ERROR){
		log_error("call receiveFrom method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	if( localPort <= 0 ){
		log_error("receiveFrom method parameter, localPort=%d, out of range", localPort);
		return E_TRANC_ParamError;		
	}
	if(flag != 0 && flag != RECEIVE_FLAG_NONBLOCK && flag != RECEIVE_FLAG_PACKET_FLUSH){
		log_error("receiveFrom method parameter, flag=%d out of range", flag);
		return E_TRANC_ParamError;
	}
	if(buffer == NULL || bufferLen <= 0){
		log_error("receiveFrom method parameter, buffer is NULL or bufferLen <= 0");
		return E_TRANC_ParamError;
	}

	index = isPortExist(localPort, PORT_STATE_PACKET);
	if(index > 0){
		logd_info("receivefrom, port exist and state is packet, just goto receive");
		goto ReceiveFrom;
	}else if(index == E_TRANC_PortAlreadyExist){
		index = isPortExist(localPort, PORT_STATE_REGISTED);
		if(index > 0){
			logd_error("receiveFrom, port exist with state is registed");
			recordIns = new TransContentPortRecord();
			//after regsit the port state is registed, so changed it
			changeRecordState(index, PORT_STATE_REGISTED, PORT_STATE_PACKET, recordIns);
			goto ReceiveFrom;

		}
		else if(canChangePortStateToRecord(localPort)){
			element.localPort = localPort;
			element.portState = PORT_STATE_PACKET;
			recordIns = new TransContentPortRecord();
			element.instance = recordIns;
			index = AddPortRecord(&element);
			if(index == E_TRANC_BufferTooSmall){
				/// no space to hold the record
				delete element.instance;
				return index;
			}
		}else{
			logd_error("receiveFrom, port exist, but can not be change state to packet");
			return E_TRANC_OpeartionNotInvalidate;
		}
	}else{
		log_error("receiveFrom method parameter, localPort=%d not exist yet, or can not be used as record!!!", localPort);
		return E_TRANC_ParamError;
	}

ReceiveFrom:
	if(timeout <= 0){		
		logd_info("receiveFrom method use timeout=%d, will cover to :%d", timeout, INT_MAX);
		timeout = INT_MAX;
	}
	log_info("call stream port instance receiveFrom instance's receiveFrom method");
	return ((TransContentPortRecord*)(portList[index].instance))->receiveFrom(flag, buffer, bufferLen, timeout, rfscb);
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// use localPort to connect to target, the localPort can not set, or set to invaliate value to create a new one
/// if use set the localPort but it can not be used as connect port, the method will return error
/// 
/// parameters:
///		target: the remote devices
///		timeout: the conect max wait time
///		localPort: use this port to connect with remote, the port must exist and can be used as connect
///		ccb: the connect callback method
/// return:
///		vid: the connect rsult port list index
///		E_TRANC_InsStateFailed: the port manager instance state error
///		E_TRANC_TIMEOUT: the conenct timeout
///		E_TRANC_ParamError: the parameters error
///		E_TRANC_NONBLOCK: the connect use sync method, will no block it
////////////////////////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::connect(const EndPoint* target, int timeout, connectCallback ccb, int localPort){
	int portExist = 0;
	int index = 0;
	NodeAddr tempAddr;
	portElement element;
	TransContentConnect* connectIns;

	if(mState == INS_STATE_ERROR){
		log_error("call connect method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	if(target->addr.serial_id <0 || target->port <= 0){
		log_error("sendTo method parameter, target.addr=%lld; port=%d", target->addr.serial_id, target->port);
		return E_TRANC_ParamError;
	}

	if( localPort <= 0 ){
		log_notice("connect method parameter, localPort=%d, out of range, will get a unique one", localPort);
		index = registPortInner(localPort, REGIST_PORT_TYPE_GET, REGIST_RETURN_VID);
		changeRecordState(index, PORT_STATE_REGISTED, PORT_STATE_CONNECTING, NULL);
		goto Connect;
	}else {
		index = isPortExist(localPort, PORT_STATE_REGISTED);
		if(index > 0){
			logd_info("connect, port with state registed exist, change state to NULL and goto connect");
			changeRecordState(index, PORT_STATE_REGISTED, PORT_STATE_CONNECTING, NULL);
			goto Connect;
		}
		else if(index == E_TRANC_PortAlreadyExist){
			logd_info("connect, port already exist, check can be used as connect");
			if(canChangePortStateToConnect(localPort)){
				logd_info("connect, port's state can be used as connecting, now add a record as connect");
				element.localPort = localPort;
				element.portState = PORT_STATE_CONNECTING;
				element.romoveCallback = NULL;
				index = AddPortRecord(&element);
				if(index == E_TRANC_BufferTooSmall){
					log_error("add port record: buffer overflow!!");
					return index;
				}
				goto Connect;
			}else{
				logd_error("connect, port exist, but state can not be changed to connect");
				return E_TRANC_OpeartionNotInvalidate;
			}
		}else{
			logd_error("connect, port not exist, now regsit it");
			index = registPortInner(localPort, REGIST_PORT_TYPE_APPLY, REGIST_RETURN_VID);
			if(index < 0){
				logd_error("connect, regist port failed, port:%d, must be used by other clients");
				return E_TRANC_PortAlreadyExist;
			}
			changeRecordState(index,  PORT_STATE_REGISTED, PORT_STATE_CONNECTING, NULL);
			goto Connect;
		}
	}

Connect:
	if(timeout <= 0){		
		logd_info("sendTo method use timeout=%d, will cover to :%d", timeout, INT_MAX);
		timeout = INT_MAX;
	}

	connectIns = new TransContentConnect();
	portList[index].instance = connectIns;
	tempAddr = target->addr;
	connectIns.setLocalPort(portList[index].localPort);
	connectIns.setTargetPort(target->port);
	connectIns.setTargetNode(&tempAddr);
	connectIns.setTimeout(timeout);
	log_info("call connect instance connect method");
	result = connectIns.connect();
	logd_info("the connect instance reutrn result is:%d ", result);
	if(result == RESPONSE_RESULT_RESET_DEFAULT){
		logd_error("port manager, the connect timed out, reset the port reocrd state to registed");
		changeRecordState(index, PORT_STATE_CONNECTING, PORT_STATE_REGISTED, NULL);
	}
	return result;;
}

//////////////////////////////////////////////////////////////////////////
/// get data from port instance, the port must be stream port or packet port
///
/// parameters:
///		port: the get data from port
///		buffer: the buffer to store data
///		len: the buffer length
///
/// return:
///		E_TRANC_InsStateFailed: the port manager istance failed
///		E_TRANC_ParamError: the parameters are not validated
///		E_TRANC_NO_DATA_AVALIABLE: no data avaliable to get
///		length: data length
//////////////////////////////////////////////////////////////////////////////////	
int TransContentPortMgr::getData(int port, char* buffer, int len){
	int index = 0;
	if(mState == INS_STATE_ERROR){
		log_error("call getData method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	if(buffer == NULL || len <= 0){
		log_error("getData method parameter, buffer is NULL or bufferLen <= 0");
		return E_TRANC_ParamError;
	}
	index = isPortExist(port, PORT_STATE_STREAM);
	if(index > 0){
		log_info("getData method parameter, localPort=%d is a stream port!!!", port);
		return ((TransContentPortStream*)(portList[index].instance))->getData(buffer, len);
	}
	index = isPortExist(port, PORT_STATE_PACKET);
	if(index > 0){
		log_info("getData method parameter, localPort=%d is a packet port!!!", port);
		return ((TransContentPortRecord*)(portList[index].instance))->getData(buffer, len);
	}
	log_error("the parameter port:%d not a stream port nor packet port", port);
	return E_TRANC_ParamError;
}

//////////////////////////////////////////////////////////
/// get local device address
///
/// parameters:
///		nodeAddr: the nodeAddress result
///
/// return:
///		E_TRANC_SUCESS: sucessfully
///		E_TRANC_ParamError: get address error, just the parameter is null
////////////////////////////////////////////////////////////
int TransContentPortMgr::getLocalAddr(NodeAddr* nodeAddr){
	if(nodeAddr == NULL)
		return E_TRANC_ParamError;
	NodeAddr tempAddr = TransContentSetting::getLocalAddr();
	*nodeAddr = tempAddr;
	return E_TRANC_SUCESS;
}

/////////////////////////////////////////////////////////////////////////////
/// get remote devices address, the vid must be a stream record
/// 
/// parameters:
///		vid: the portlist index
///		nodeAddr: the address to store the address result
///
/// return:
///		E_TRANC_InsStateFailed: the port manager instance state error
///		E_TRANC_ParamError: the parameters of the method failed
///		E_TRANC_InnerLogicError: the vid instance is null
///		E_TRANC_SUCESS: get the address sucessfully
////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::getRemoteAddr(vroute_t vid, NodeAddr* nodeAddr){
	if(mState == INS_STATE_ERROR){
		log_error("call getRemoteAddr method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	if( vid < 0 || vid > this->mPortCapacity || nodeAddr == NULL){
		log_error("getRemoteAddr method parameter, vid=%d, out of range", vid);
		return E_TRANC_ParamError;		
	}
	if(portList[vid].localPort == 0){
		log_error("getRemoteAddr method parameter, vid=%d's localPort==0", vid);
		return E_TRANC_ParamError;
	}
	if(portList[vid].instance == NULL){
		log_error("getRemoteAddr port reocrd, but the instance is NULL");
		return E_TRANC_InnerLogicError;
	}
	if(portList[vid].portState != PORT_STATE_STREAM){
		log_error("port state is:%d, can not call getRemoteAddr", portList[vid].portState);
		return E_TRANC_ParamError;
	}
	log_info("get remote port from stream instace");
	return ((TransContentPortStream*)(portList[vid].instance))->getRemoteAddr(nodeAddr);
}

/////////////////////////////////////////////////////////////////////////////
/// get remote devices connect port, the vid must be a stream record
/// 
/// parameters:
///		vid: the portlist index
///		nodeAddr: the address to store the address result
///
/// return:
///		E_TRANC_InsStateFailed: the port manager instance state error
///		E_TRANC_ParamError: the parameters of the method failed
///		E_TRANC_InnerLogicError: the vid instance is null
///		port: the port value
///////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::getRemotePort(vroute_t vid){
	if(mState == INS_STATE_ERROR){
		log_error("call getRemoteAddr method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	if( vid < 0 || vid > this->mPortCapacity){
		log_error("getRemoteAddr method parameter, vid=%d, out of range", vid);
		return E_TRANC_ParamError;		
	}
	if(portList[vid].localPort == 0){
		log_error("getRemoteAddr method parameter, vid=%d's localPort==0", vid);
		return E_TRANC_ParamError;
	}
	if(portList[vid].instance == NULL){
		log_error("getRemoteAddr port reocrd, but the instance is NULL");
		return E_TRANC_InnerLogicError;
	}
	if(portList[vid].portState != PORT_STATE_STREAM){
		log_error("port state is:%d, can not call getRemoteAddr", portList[vid].portState);
		return E_TRANC_ParamError;
	}
	log_info("get remote port from stream instace");
	return ((TransContentPortStream*)(portList[vid].instance))->getRemotePort();
}

/////////////////////////////////////////////////////////////////////////////
/// get remote devices address, the vid must be a stream record
/// 
/// parameters:
///		vid: the portlist index
///		nodeAddr: the address to store the address result
///
/// return:
///		E_TRANC_InsStateFailed: the port manager instance state error
///		E_TRANC_ParamError: the parameters of the method failed
///		E_TRANC_InnerLogicError: the vid instance is null
///		E_TRANC_SUCESS: get remote device info sucessfully
///////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::getRemote(vroute_t vid, EndPoint* dest){
	if(mState == INS_STATE_ERROR){
		log_error("call getRemoteAddr method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	if( vid < 0 || vid > this->mPortCapacity || dest == NULL){
		log_error("getRemoteAddr method parameter, vid=%d, out of range", vid);
		return E_TRANC_ParamError;		
	}
	if(portList[vid].localPort == 0){
		log_error("getRemoteAddr method parameter, vid=%d's localPort==0", vid);
		return E_TRANC_ParamError;
	}
	if(portList[vid].instance == NULL){
		log_error("getRemoteAddr port reocrd, but the instance is NULL");
		return E_TRANC_InnerLogicError;
	}
	if(portList[vid].portState != PORT_STATE_STREAM){
		log_error("port state is:%d, can not call getRemoteAddr", portList[vid].portState);
		return E_TRANC_ParamError;
	}
	log_info("get remote port from stream instace");
	return ((TransContentPortStream*)(portList[vid].instance))->getRemote(dest);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
/// get the transformer node devices address list
/// 
/// parameters:
///		port: the port get the response
///		tracertType: the tracert flag, to set tracert forward or both forward and back
///		target: the target to tracert
///		nodeList: the array to store the node address
///		nodeCount: the list count
///		timeout: the max wait time
///		ttcb: tracert callback method
///
/// return:
///		E_TRANC_InsStateFailed: port manager instance state error
///		E_TRANC_PORT_STATE_ERROR: port is registing and can not be used
///		E_TRANC_TIMEOUT: tracert timeout
///		E_TRANC_NONBLOCK: use sync method, so will not block the caller
///		E_TRANC_BufferTooSmall: buffer is too small to hold info
///		E_TRANC_PortNotExist: the port not exist yet
///		count: the node count
/////////////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::tracertTarget(int port, int tracertType, const NodeAddr* target, NodeAddr* nodeList, int nodeCount, int timeout, tarcertTargetCallback ttcb){
	int index=0;
	portElement tempElement;
	TransContentFuncCallTracertTarget* tcftt;

	if(mState == INS_STATE_ERROR){
		log_error("call tracertTarget method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	
	logd_info("tracert target, check port:%d with state tracert target exist", port);
	index = isPortExist(port, PORT_STATE_FUNC_TRACERT_TARGET);
	if(index > 0){
		logd_error("tracert target, the port:%d with tracert target state already exist !!", port);
		return E_TRANC_PortAlreadyExist;
	}else if(index == E_TRANC_PortAlreadyExist){
		logd_info("tracert target check port with state registed exist");
		index = isPortExist(port, PORT_STATE_REGISTED);
		if(index > 0){
			logd_info("tracert target, port with regsit state exist, now change state and goto tracert");
			changeRecordState(index, PORT_STATE_REGISTED, PORT_STATE_FUNC_TRACERT_TARGET, NULL);
			goto TracertTarget;
		}

		logd_info("tracert target, the port:%d already exist, check the port can be used as tracert");
		if(canPortStateChangedToFunctionRelate(port)){
			logd_info("tracert target, the port:%d can be use to tracert target", port);
			tempElement.localPort = port;
			tempElement.portState = PORT_STATE_FUNC_TRACERT_TARGET;
			tempElement.instance = NULL;
			tempElement.romoveCallback = NULL;
			index = AddPortRecord(&tempElement);
			if(index == E_TRANC_BufferTooSmall){
				log_error("port list record too many to hold!!!");
				return index;
			}
			goto TracertTarget;
		}else{
			logd_error("tracert target, the port:%d can not be used to tracert target", port);
			return E_TRANC_OpeartionNotInvalidate;
		}
	}else{
		logd_error("tracert target, the port:%d not exist, regist it");
		index = registPortInner(port, REGIST_PORT_TYPE_APPLY, REGIST_RETURN_VID);
		if(index < 0){
			logd_error("tracer target, the port:%d regist failed, exist already");
			return E_TRANC_PortAlreadyExist;
		}
		changeRecordState(index, PORT_STATE_REGISTED, PORT_STATE_FUNC_TRACERT_TARGET, NULL);
	}

TracertTarget:
	tcftt = new TransContentFuncCallTracertTarget();
	portList[index].instance = tcftt;
	
	tcftt->setTimeout(timeout);
	tcftt->setLocalPort(port);
	tcftt->setTracertFlag(tracertType);
	tcftt->setTracertTarget(target);
	tcftt->setTracertTargetCallback(ttcb);
	
	logd_info("tracert target, begin to call tracert");
	//return port function
	return tcftt->tracertTarget();
}


////////////////////////////////////////////////////////////////////////////////////////////////////////
/// get target device info, use give condtion
/// 
/// parameters:
///		port: the port get the response
///		type: the query condtion type
///		valueLength: the query condtion value length
///		value: the query condtion value
///		result: the quered device info, the parameter can not be NULL
///		timeout: the max wait time
//		qtcb: query target device callback
///
/// return:
///		E_TRANC_InsStateFailed: port manager instance state error
///		E_TRANC_PORT_STATE_ERROR: port is registing and can not be used
///		E_TRANC_TIMEOUT: tracert timeout
///		E_TRANC_NONBLOCK: use sync method, so will not block the caller
///		E_TRANC_BufferTooSmall: buffer is too small to hold info
///		E_TRANC_PortNotExist: the port not exist yet
///		result: query sucessfully or failed
/////////////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::queryTarget(int port, int type, int valueLength, void* value, deviceInfo* result, int timeout, queryTargetCallback qtcb){
	int index=0;
	portElement tempElement;
	TransContentFuncCallQueryTarget* tcfcqt;
	if(mState == INS_STATE_ERROR){
		log_error("call queryTarget method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}

	logd_info("query target, check port:%d with state query target exist", port);
    index = isPortExist(port, PORT_STATE_FUNC_QUERY_TARGET);
    if(index > 0){
        logd_error("query target, the port:%d with query target state already exist !!", port);
        return E_TRANC_PortAlreadyExist;
    }else if(index == E_TRANC_PortAlreadyExist){
        logd_info("query target check port with state registed exist");
        index = isPortExist(port, PORT_STATE_REGISTED);
        if(index > 0){
            logd_info("query target, port with regsit state exist, now change state and goto query");
            changeRecordState(index, PORT_STATE_REGISTED, PORT_STATE_FUNC_QUERY_TARGET, NULL);
            goto QueryTarget;
        }

        logd_info("query target, the port:%d already exist, check the port can be used as query");
        if(canPortStateChangedToFunctionRelate(port)){
            logd_info("query target, the port:%d can be use to query target", port);
            tempElement.localPort = port;
            tempElement.portState = PORT_STATE_FUNC_QUERY_TARGET;
            tempElement.instance = NULL;
            tempElement.romoveCallback = NULL;
            index = AddPortRecord(&tempElement);
            if(index == E_TRANC_BufferTooSmall){
                log_error("port list record too many to hold!!!");
                return index;
            }
            goto QueryTarget;
        }else{
			logd_error("query target, the port:%d can not be used to query target", port);
            return E_TRANC_OpeartionNotInvalidate;
        }
    }else{
        logd_error("query target, the port:%d not exist, regist it");
        index = registPortInner(port, REGIST_PORT_TYPE_APPLY, REGIST_RETURN_VID);
        if(index < 0){
            logd_error("query target, the port:%d regist failed, exist already");
            return E_TRANC_PortAlreadyExist;
        }
        changeRecordState(index, PORT_STATE_REGISTED, PORT_STATE_FUNC_QUERY_TARGET, NULL);
    }

QueryTarget:
	tcfcqt = new TransContentFuncCallQueryTarget();
    portList[index].instance = tcfcqt;

	//result whether sucess
	tcfcqt->setTimeout(timeout);
	tcfcqt->setLocalPort(port);
	tcfcqt->setQueryValue(type, value, valueLength);
	tcfcqt->setFinishedCallback(qtcb);

	logd_info("query target, call the instance query method");
	//return port function
	return tcfcqt->query();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
/// check target reachable
/// 
/// parameters:
///		port: the port get the response
///		target: the devcie to check
///		timeout: the max wait time
//		tracb: target reachable callback method
///
/// return:
///		E_TRANC_InsStateFailed: port manager instance state error
///		E_TRANC_PORT_STATE_ERROR: port is registing and can not be used
///		E_TRANC_TIMEOUT: tracert timeout
///		E_TRANC_NONBLOCK: use sync method, so will not block the caller
///		E_TRANC_BufferTooSmall: buffer is too small to hold info
///		E_TRANC_PortNotExist: the port not exist yet
///		result: reachable or not
/////////////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::targetReachable(int port, const NodeAddr* target, int timeout, targetReachAbleCallback tracb){
	int index=0;
	int newPort = 0;
	portElement tempElement;
	TransContentFuncCallTargetReachable* tcfctr;
	if(mState == INS_STATE_ERROR){
		log_error("call receiveFrom method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}

	logd_info("target reachable, check port:%d with state target reachable exist", port);
    index = isPortExist(port, PORT_STATE_FUNC_TARGET_REACHABLE);
    if(index > 0){
        logd_error("target reachable, the port:%d with target reachable state already exist !!", port);
        return E_TRANC_PortAlreadyExist;
    }

	else if(index == E_TRANC_PortAlreadyExist){
        logd_info("target reachable check port with state registed exist");
        index = isPortExist(port, PORT_STATE_REGISTED);
        if(index > 0){
            logd_info("target reachable, port with regsit state exist, now change state and goto query");
            changeRecordState(index, PORT_STATE_REGISTED, PORT_STATE_FUNC_TARGET_REACHABLE, NULL);
            goto TargetReachable:;
        }

        logd_info("target reachable, the port:%d already exist, check the port can be used as target reachable");
        if(canPortStateChangedToFunctionRelate(port)){
            logd_info("target reachable, the port:%d can be use to target reachable", port);
            tempElement.localPort = port;
            tempElement.portState = PORT_STATE_FUNC_TARGET_REACHABLE;
            tempElement.instance = NULL;
            tempElement.romoveCallback = NULL;
            index = AddPortRecord(&tempElement);
            if(index == E_TRANC_BufferTooSmall){
                log_error("port list record too many to hold!!!");
                return index;
            }
            goto TargetReachable:;
        }else{
            logd_error("target reachable, the port:%d can not be used to target reachable", port);
            return E_TRANC_OpeartionNotInvalidate;
        }
    }else{
        logd_error("target reachable, the port:%d not exist, regist it");
        index = registPortInner(port, REGIST_PORT_TYPE_APPLY, REGIST_RETURN_VID);
        if(index < 0){
            logd_error("target reachable, the port:%d regist failed, exist already");
            return E_TRANC_PortAlreadyExist;
        }
        changeRecordState(index, PORT_STATE_REGISTED, PORT_STATE_FUNC_TARGET_REACHABLE, NULL);
    }

TargetReachable:
	tcfctr = new TransContentFuncCallTargetReachable()
    portList[index].instance = tcfctr;
	
	//result whether sucess
	tcfctr->setTimeout(timeout);
	tcfctr->setLocalPort(port);
	tcfctr->setTarget(target);
	tcfctr->setFinishCallback(tracb);

	logd_error("target reachable, call the instance reachable method");
	//return port function
	return tcfctr->targetReachable();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
/// set fxied path to target device
///
/// parameters:
///		target: the path to which
///		nodeList: the fiexed path node value
///		nodeCount: the node count in nodeList
///	return:
//		E_TRANC_ParamError: the target is NULL or the nodeList is NULL or the nodeCount out of range
//		E_TRANC_SUCESS: the method operation sucefully
/////////////////////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::setFixedNodeList(const NodeAddr* target, const NodeAddr* nodeList, int nodeCount){
	if(target == NULL || nodeList == NULL || nodeCount < FIXEDPATH_NODE_COUNT_MIN || nodeCount > FIXEDPATH_NODE_COUNT_MAX){
		return E_TRANC_ParamError;
	}
	return TransContentGetStackInfo::setFixedPath(target, nodeList, nodeCount);
}

//////////////////////////////////////////////////////////////////////////
/// get the vid relative localPort
///
/// parameters:
///		vid: the vroute index to look
///
/// return:
///		E_TRANC_InsStateFailed: the port manager instance state error
///		E_TRANC_ParamError: the parameter of the method failed
///		E_TRANC_InnerLogicError: the vroute system logic error
///		E_TRANC_OpeartionNotInvalidate: the vid record port state not a stream state
///		port: the vid relateive port
//////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::getVroutePort(vroute_t vid){
	if(mState == INS_STATE_ERROR){
		log_error("call tracertTarget method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	if( vid < 0 || vid > this->mPortCapacity){
		log_error("tracertTarget method parameter, vid=%d, out of range", vid);
		return E_TRANC_ParamError;		
	}
	if(portList[vid].localPort == 0){
		log_error("tracertTarget method parameter, vid=%d's localPort==0", vid);
		return E_TRANC_ParamError;
	}
	if(portList[vid].instance == NULL){
		log_error("tracertTarget port reocrd, but the instance is NULL");
		return E_TRANC_InnerLogicError;
	}
	if(portList[vid].portState != PORT_STATE_STREAM){
		log_error("port state is:%d, can not call tracertTarget", portList[vid].portState);
		return E_TRANC_OpeartionNotInvalidate;
	}
	return portList[vid].localPort;
}

////////////////////////////////////////////////////////////////////////////////////////
/// get the returned error number detials error information
///
/// parameters:
///		errno_num: the error code
///		buffer: the buffer to store the error info, can not be NULL
///		bufferLen: the buffer length
///
///	return:
///		E_TRANC_InsStateFailed: the port manager instance state error
///		E_TRANC_ParamError: the method parameter error
///		E_TRANC_BufferTooSmall: the buffer space too small to hold all information
///		length: the error information length
///		0: no such error code
//////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::getErrorInfo(int errno_num, char* buffer, int bufferLen){
	int len;
	if(mState == INS_STATE_ERROR){
		log_error("call getErrorInfo method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	if(buffer == NULL){
		return E_TRANC_ParamError;
	}
	switch(errno_num){
		case E_TRANC_SUCESS:
			len =  strlen("sucess, no error");
			if(bufferLen <= len){
				logd_error("buffer too small to hold the error message");
				return E_TRANC_BufferTooSmall;
			}
			memset(buffer, 0x00, bufferLen);
			memcpy(buffer, "sucess, no error", len);
			return len +1;

		case E_TRANC_PortAlreadyExist:
			len =  strlen("port manager show the port exist, but the method should not use exist port");
			if(bufferLen <= len){
				logd_error("buffer too small to hold the error message");
				return E_TRANC_BufferTooSmall;
			}
			memset(buffer, 0x00, bufferLen);
			memcpy(buffer, "port manager show the port exist, but the method should not use exist port", len);
			return len +1;
		case E_TRANC_PortNotExist:
			len =  strlen("port manager show the port not exist, but the method should use exist port");
			if(bufferLen <= len){
				logd_error("buffer too small to hold the error message");
				return E_TRANC_BufferTooSmall;
			}
			memset(buffer, 0x00, bufferLen);
			memcpy(buffer, "port manager show the port not exist, but the method should use exist port", len);
			return len +1;

		case E_TRANC_InsStateFailed:
			len =  strlen("call instance method but the instance state not suitable!");
			if(bufferLen <= len){
				logd_error("buffer too small to hold the error message");
				return E_TRANC_BufferTooSmall;
			}
			memset(buffer, 0x00, bufferLen);
			memcpy(buffer, "call instance method but the instance state not suitable!", len);
			return len +1;

		case E_TRANC_SystemError:
			len =  strlen("should call strerror() or perror() to get more details");
			if(bufferLen <= len){
				logd_error("buffer too small to hold the error message");
				return E_TRANC_BufferTooSmall;
			}
			memset(buffer, 0x00, bufferLen);
			memcpy(buffer, "should call strerror() or perror() to get more details", len);
			return len +1;

		case E_TRANC_ParamError:
			len =  strlen("call method but passed error parameter");
			if(bufferLen <= len){
				logd_error("buffer too small to hold the error message");
				return E_TRANC_BufferTooSmall;
			}
			memset(buffer, 0x00, bufferLen);
			memcpy(buffer, "call method but passed error parameter", len);
			return len +1;

		case E_TRANC_BufferTooSmall:
			len =  strlen("pass a buffer to get info, but the buffer too small to hold all info");
			if(bufferLen <= len){
				logd_error("buffer too small to hold the error message");
				return E_TRANC_BufferTooSmall;
			}
			memset(buffer, 0x00, bufferLen);
			memcpy(buffer, "pass a buffer to get info, but the buffer too small to hold all info", len);
			return len +1;

		case E_TRANC_OpeartionNotInvalidate:
			len =  strlen("call method on a port, which state not be allowed to do so");
			if(bufferLen <= len){
				logd_error("buffer too small to hold the error message");
				return E_TRANC_BufferTooSmall;
			}
			memset(buffer, 0x00, bufferLen);
			memcpy(buffer, "call method on a port, which state not be allowed to do so", len);
			return len +1;

		case E_TRANC_InnerLogicError:
			len =  strlen("vroute system internal logical error, usally the port state error, or instance error");
			if(bufferLen <= len){
				logd_error("buffer too small to hold the error message");
				return E_TRANC_BufferTooSmall;
			}
			memset(buffer, 0x00, bufferLen);
			memcpy(buffer, "vroute system internal logical error, usally the port state error, or instance error", len);
			return len +1;
		
		case E_TRANC_BUFFER_FULL:
			len =  strlen("buffer capacity reached the max limit");
			if(bufferLen <= len){
				logd_error("buffer too small to hold the error message");
				return E_TRANC_BufferTooSmall;
			}
			memset(buffer, 0x00, bufferLen);
			memcpy(buffer, "buffer capacity reached the max limit", len);
			return len +1;

		case E_TRANC_ACCEPT_FULL:
			len =  strlen("accept method received max limits count connect");
			if(bufferLen <= len){
				logd_error("buffer too small to hold the error message");
				return E_TRANC_BufferTooSmall;
			}
			memset(buffer, 0x00, bufferLen);
			memcpy(buffer, "accept method received max limits count connect", len);
			return len +1;

		case E_TRANC_TIMEOUT:
			len =  strlen("operation timeout");
			if(bufferLen <= len){
				logd_error("buffer too small to hold the error message");
				return E_TRANC_BufferTooSmall;
			}
			memset(buffer, 0x00, bufferLen);
			memcpy(buffer, "operation timeout", len);
			return len +1;

		case E_TRANC_NONBLOCK:
			len =  strlen("the method is a sync method, will not block the caller");
			if(bufferLen <= len){
				logd_error("buffer too small to hold the error message");
				return E_TRANC_BufferTooSmall;
			}
			memset(buffer, 0x00, bufferLen);
			memcpy(buffer, "the method is a sync method, will not block the caller", len);
			return len +1;

		case E_TRANC_NO_DATA_AVALIABLE:
			len =  strlen("the port have no avaliable data");
			if(bufferLen <= len){
				logd_error("buffer too small to hold the error message");
				return E_TRANC_BufferTooSmall;
			}
			memset(buffer, 0x00, bufferLen);
			memcpy(buffer, "the port have no avaliable data", len);
			return len +1;

		case E_TRANC_PORT_STATE_ERROR:
			len =  strlen("port state show the port now can not be used");
			if(bufferLen <= len){
				logd_error("buffer too small to hold the error message");
				return E_TRANC_BufferTooSmall;
			}
			memset(buffer, 0x00, bufferLen);
			memcpy(buffer, "port state show the port now can not be used", len);
			return len +1;
	}
	return 0;
}

/////////////////////////////////////////////////////////////////////////////////////
/// check the port is exist already
///
/// parameter:
///		port: the query port
///	
/// return:
///		E_TRANC_BufferTooSmall: the port list space full
///		E_TRANC_InsStateFailed: the port manger instance error
///		E_TRANC_ParamError: the port is out of range
///		1: the port exist
///		0: the port not exist
//////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::isPortAlreadyExist(int port){
	int index;
	if(mState == INS_STATE_ERROR){
		log_error("call isPortAlreadyExist method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	if(port <= 0 ){
		log_error("isPortAlreadyExist method parameter, port=%d, out of range", port);
		return E_TRANC_ParamError;	
	}
	index = isPortExist(port);
	if(index > 0){
		logd_info("the port:%d have already existed in the port list", port);
		return 1;
	}
	return registPortInner(port, REGIST_PORT_TYPE_TEST, REGIST_RETURN_EXIST);
}

//////////////////////////////////////////////////////////////////////////////////
/// get a unique port from stack
///
/// return:
///		E_TRANC_InsStateFailed: the port manager instance state error
///		E_TRANC_BufferTooSmall: the port list count reached the max limit
///		E_TRANC_TIMEOUT: the operation timeout
///		E_TRANC_NONBLOCK: call this method use sync style
///		port: the get port
/////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::getAPort(){
	debug_enter();
	logd_info("get A port, call regist port inner to get an unique port");
	return registPortInner(-1, REGIST_PORT_TYPE_GET, REGIST_RETURN_PORT;	
}

///////////////////////////////////////////////////////////////////////////////////////////////
/// regist a port to stack
///
/// parameter:
///		port: regist target port
///		timeout: regist timeout value
///		rgcb: regsit callbacnk method
///
///	return:
///		E_TRANC_InsStateFailed: the port manager instance state error
///		E_TRANC_ParamError: the parameter of this method error
///		E_TRANC_BufferTooSmall: the port list count reached the max capacity limit
///		E_TRANC_PortAlreadyExist: the port has been registed already
///		E_TRANC_TIMEOUT: the operation wait timeout
///		E_TRANC_NONBLOCK: call this method use sync style
///		port: the regist result, sucess or failed
/////////////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::registPort(int port){
	debug_enter();
	logd_info("regist port, call regist port inner to regist a port, with result is 0 or 1");
	return registPortInner(port, REGIST_PORT_TYPE_APPLY, REGIST_RETURN_TEST);	
}

//////////////////////////////////////////////////////////////////////////////////////////
/// set the port record close callback method
///
/// parameters:
///		port: the port to set close callback method
///		pccb: the port close callback
///	return:
///		E_TRANC_InsStateFailed: the port manager instance state error
///		E_TRANC_ParamError: the parameter port is out of range
///		E_TRANC_PortNotExist: the port not exist
///		E_TRANC_SUCESS: set the port close callback sucessfully
//////////////////////////////////////////////////////////////////////////////////////////	
int TransContentPortMgr::setPortClosingCallback(int port, portClosingCallback pccb){
	if(mState == INS_STATE_ERROR){
		log_error("call setPortClosingCallback method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}

	if(port <= 0){
		log_error("parameter port: %d out of range!", port);
		return E_TRANC_ParamError;
	}

	for(int i=0, count=0; i< mPortCapacity && count < mPortCount; ++i){
        if(portList[i].localPort != 0){
            ++count;
            if(portList[i].localPort == port){
                /// set callback
					portList[i].romoveCallback = pccb;
                }
            }
        }
    }
	return E_TRANC_SUCESS;
}

//////////////////////////////////////////////////////////////////////////////////////////
/// set the vid record close callback method
///
/// parameters:
///		vid: the port record index
///		pccb: the port close callback
///	return:
///		E_TRANC_InsStateFailed: the port manager instance state error
///		E_TRANC_ParamError: the parameter port is out of range
///		E_TRANC_SUCESS: set the port close callback sucessfully
//////////////////////////////////////////////////////////////////////////////////////////	
int TransContentPortMgr::setPortClosingCallbackVid(vroute_t vid, portClosingCallback pccb){
	if(mState == INS_STATE_ERROR){
		log_error("call setPortClosingCallbackVid method, the instance state error!!");
		return E_TRANC_InsStateFailed;
	}
	if( vid < 0 || vid > this->mPortCapacity){
		log_error("setPortClosingCallbackVid method parameter, vid=%d, out of range", vid);
		return E_TRANC_ParamError;		
	}
	if(portList[vid].localPort == 0){
		log_error("setPortClosingCallbackVid method parameter, vid=%d's localPort==0", vid);
		return E_TRANC_ParamError;
	}
	portList[vid].romoveCallback = pccb;
	return E_TRANC_SUCESS;
}

//////////////////////////////////////////////////////////////////////////////////////////
/// get the port record close callback method
///
/// parameters:
///		port: get the port close callback method
///
///	return:
///		portClosingCallback: the port's closing callback
///		NULL: the port closing callback is NULL or other error
//////////////////////////////////////////////////////////////////////////////////////////	
portClosingCallback TransContentPortMgr::getPortClosingCallback(int port){
	int index = 0;
	if(mState == INS_STATE_ERROR){
		log_error("call setPortClosingCallback method, the instance state error!!");
		return NULL;
	}

	if(port <= 0){
		log_error("the parameter port: %d of this mehtod out of range", port);
		return NULL;
	}
	index = isPortExist(port);
	if(index == E_TRANC_PortNotExist){
		log_error("setPortClosingCallback method parameter, localPort=%d not exist yet!!!", port);
		return NULL;
	}

	return portList[index].romoveCallback;
}

//////////////////////////////////////////////////////////////////////////////////////////
/// get the port list record close callback method
///
/// parameters:
///		vid: get the port list record index close callback method
///
///	return:
///		portClosingCallback: the port's closing callback
///		NULL: the port closing callback is NULL or other error
//////////////////////////////////////////////////////////////////////////////////////////	
portClosingCallback TransContentPortMgr::getPortClosingCallbackVid(vroute_t vid){
	if(mState == INS_STATE_ERROR){
		log_error("call getPortClosingCallbackVid method, the instance state error!!");
		return NULL;
	}
	if( vid < 0 || vid > this->mPortCapacity){
		log_error("getPortClosingCallbackVid method parameter, vid=%d, out of range", vid);
		return NULL;		
	}
	if(portList[vid].localPort == 0){
		log_error("getPortClosingCallbackVid method parameter, vid=%d's localPort==0", vid);
		return NULL;
	}
	return portList[vid].romoveCallback;
}

////////////////////////////////////////////////////////////
/// change a port record state, the port record can be pointed out by port or index, but must be one
/// first check index value, if index value invalidate, use port, other will use index
/// 
/// parameters:
/// 	port: the target port state to change;
///		_index: the port record index state to change;
///		oldState: the port old state
///		newState: the target state to change
///		newInstance: the target instance to change
///
/// return:
///		E_TRANC_ParamError: when both port and index are invalidate;
///		E_TRANC_OpeartionNotInvalidate: when oldState not match the record
///		E_TRANC_SUCESS: change state sucessfully
//////////////////////////////////////////////////////////////
int TransContentPortMgr::changeRecordState(int index, int oldState, int newState, void* newInstance){
	debug_enter();
	if(index < 0){
		logd_error("changa record state error, the index <0 ");
		return E_TRANC_ParamError;
	}

	if(portList[index].portState != oldState){
		log_error("port state not match!! %d != %d", portList[index].portState, oldState);
		return E_TRANC_OpeartionNotInvalidate;
	}

	portList[index].portState = newState;
	if(portList[index].instance != NULL){
		log_warmming("change port state, now destroy the port instance");
		delete portList[index].instance;
	}

	portList[index].instance = newInstance;
	return E_TRANC_SUCESS;
}

///////////////////////////////////////////////////////////////////////////////////////////
/// increase the port list capacity to double space, if not reached the max capacity
///
/// return:
///		E_TRANC_BUFFER_FULL: the capacity reached the max limit
///		E_TRANC_SystemError: alloc space failed
///		E_TRANC_SUCESS: alloc sucessfully
/////////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::increasePortRecordSpace(){
/*	if(mPortCapacity >= ALLPORT_COUNT_MAX){
		log_error("want increase port record space, but reached the max limit");
		return E_TRANC_BUFFER_FULL;
	}
*/
	/// the function only be called at addRecord, and the addRecord use mutex, so there is not
	debug_enter();
	logd_info("increase port record space, reset capacity to double and relloc the space");
	mPortCapacity *= 2;
	portList = (portElement*)realloc(portList, mPortCapacity * sizeof(portElement));
	if(portList == NULL){
		logd_fata_error("ow!! alloc memory for all port list failed!! %s", strerror(errno));
		//should restart client
		//restart();
		//log_fata_error("restart the client!!");
		return E_TRANC_SystemError;
	}
	logd_info("increase port record space, sucessfully");
	return E_TRANC_SUCESS;
}

void TransContentPortMgr::restart(){
}

////////////////////////////////////////////////////////////////////////////////////////////
/// remote the index reocrd or all the same port record
///
/// parameter:
///		port: remove all the port records
///		index: remove the index record
///
/// return:
///		E_TRANC_SUCESS: operation sucessfully
/////////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::removePortRecord(int port, int index){
	int __index = 0;
	debug_enter();
	pthread_mutex_lock(&mutex_port);
	if(port <= 0){
		goto Index;
	}

	logd_info("remote port record, now remote port :%d", port);
	pthread_mutex_lock(&mutex_port);
	/// delete the port
	while(__index < mPortCapacity && mPortCount){
		if(portList[__index].localPort == port){
			log_info("remove the port :%d, index=%d", port, __index);
			portList[__index].localPort = 0;
			portList[__index].portState = PORT_STATE_ERROR;
			portList[__index].romoveCallback = NULL;
			if(portList[__index].instance != NULL){
				delete portList[__index].instance;
				portList[__index].instance = NULL;
			}
			--mPortCount;
		}
		++__index;
	}

Index:
	/// delete the index
	logd_info("remote port record, now remote index at :%d", index);
	if(index <= -1){
		goto End;
	}
	if(portList[__index].localPort == 0){
		logd_info("remove port record, the index's localPort = 0");
		goto End;
	}
	--mPortCount;
	portList[__index].localPort = 0;
	portList[__index].portState = 0;
	portList[__index].romoveCallback = NULL;
	if(portList[__index].instance != NULL){
		delete portList[__index].instance;
		portList[__index].instance = NULL;
	}
End:
	pthread_mutex_unlock(&mutex_port);
	return E_TRANC_SUCESS;
}

////////////////////////////////////////////////////////////
/// dispatcher received data from stack to relative sub mode
/// for setting or some message type which have no localport, just dispatcher to settingDispatcher
/// after setttingDiapatcher the message must have a localPort, so use withPortDispatcher
/// after dispatcher, just return
////////////////////////////////////////////////////////////
void TransContentPortMgr::dispatcher(char* buffer, int index){
	int mainCode = buffer[0];
	int subCode =buffer[1];
	int result = RESPONSE_RESULT_NOACTION;
	int localPort = 0;
	
	// dispatcher for port list 
	result = dispatcherForPortList(buffer, index);
	if(result == 1){
		logd_info("port manager port list dispispathcer, deal the dispatcher finished");
		return;
	}
	//dispatcher for instance
	localPort = TransContentAssis::INTN2L((short*)(buffer+2));
	for(int i=0, count = 0; i< mPortCapacity &&  count < mPortCount; ++ i){
		if(portList[i].localPort == localPort){
			count++;
			result = dispatcherForPortInstance(buffer, index);
			if(result == 1){
				logd_info("port manager port instance dispispathcer, deal the dispatcher finished");
				return;
			}
		}
	}

	//dispthcer for exception
	logd_info("port manager, the port=%d, maincode = %d, subCode = %d, not be deal by instance or port list", localPort, mainCode, subCode);
	dispatcherForException(buffer, index);
	return;
}

///////////////////////////////////////////////////////////////////////////
/// heart beat for port, used to check port exist
/// if port not exist any more, send a port closing protocol
/// 1. localPort state may be in registing, so the local port may lager than stack.
/// 2. localPort may be closing, so the localPort may be not exist.
/// the heatbeat direction is stack to client
///
/// parameter:
///		buffer: the heartbeat content
///		index: the buffer index in memory pool
///
//////////////////////////////////////////////////////////////////////////////
void TransContentPortMgr::heartBeatResponse(char* buffer, int index){
	int localPort;
	int subCode = buffer[1];
	int result = 1;
	int portState = PORT_STATE_ERROR;
	debug_enter();
	localPort = transContentPortStateProtocol::getPacketPort(buffer, DUMP_PROTOCOL_PACKET_IN);
	if(subCode == message_type_heartBeat_sub_inner && (isPortExist(localPort) == E_TRANC_PortNotExist)){
		//port not exist
		closePortToStack(localPort);
		TransContentMemory::getInstance()->releaseBuffer(index);
	}else if(subCode == message_type_heartBeat_sub_outter){
		portState = buffer[18];
		if(portState != PORT_STATE_STREAM){
			logd_error("port list heart beat response, the port state not be stream");
			closePortToRemote(buffer, index);
		}else{
			result = isPortExist(localPort, PORT_STATE_STREAM);
			if(result == E_TRANC_PortNotExist){
				logd_error("port list heart beat response, the port state with stream not exist!");
				closePortToRemote(buffer, index);
			}else{
				logd_info("port list heart beat response, call the port stream instance response");
				portList[result].instance->response(buffer, index);
			}
		}
	}
	debug_leave();
	return;
}

/////////////////////////////////////////////////////////////////////////
/// remote port use heartbeat to query port exist
///		this method show that the port at stram state not exist, remote should close the port
///
///	parameter:
///		buffer: the information contant
///		index: the buffer in the memroy pool
///
///////////////////////////////////////////////////////////////////////////
void TransContentPortMgr::closePortToRemote(char* buffer, int index){
	int remotePort, localPort, action;
	NodeAddr remoteAddr;
	char heartBuffer[48]={0};
	debug_enter();
	logd_info("close port to remote, extract info from buffer");
	localPort = TransContentAssis::INTN2L(*(int*(bufffer+2)));
	remotePort = TransContentAssis::INTN2L(*(int*(bufffer+6)));
	remoteAddr = TransContentAssis::NodeAddrN2L(*(NodeAddr*(buffer+10)));

	logd_info("close port to remote, start to release the buffer");
	TransContentMemory::getInstance()->releaseBuffer(index);
	logd_info("close port to remote, construct packet to remote");
	*(short*(buffer)) = (short)31;
	buffer[2] = message_type_heatBeat;
	*(NodeAddr*(buffer+3)) = TransContentAssis::NodeAddrL2N(&remoteAddr);
	buffer[11] = (char)SEND_FLAG_USE_PATH_OPTION;
	*(short*(buffer+12)) = TransContentAssis::SHORTL2N(20);
	buffer[14] = message_type_heatBeat;
	buffer[15] = message_type_heartBeat_sub_outter;
	*(int*(buffer+16)) = TransContentAssis::INTL2N(remotePort);
	*(int*(buffer+20)) = TransContentAssis::INTL2N(localPort);
	*(NodeAddr*(buffer+24)) = TransContentSetting::getLocalAddrNetBytes();
	buffer[32] = (char)PORT_STATE_STREAM;
	buffer[33] = heartBeat_Action_ClosePort;

	logd_info("close port to remote, start send data to remote");
	TransContentDispatcher::getInstance()->sendDataDataToStack(heartBuffer, 33);
	debug_leave();
	return;
}

/////////////////////////////////////////////////////////////////////////////
/// close stack port
///
/// parameter:
///		port: the port to close
/////////////////////////////////////////////////////////////////////////////
void TransContentPortMgr::closePortToStack(int port){
	char buffer[24] = {0};
	transContentPortStateProtocol::setPacketLength(buffer, 8);
	transContentPortStateProtocol::setPacketMainMessageCode(buffer, message_type_inner_port_close);
	transContentPortStateProtocol::setPacketPort(buffer, port);
	if(TransContentDispatcher::getInstance()->sendDataRegistToStack(buffer, 8) != E_TRANC_SUCESS){
		log_error("send port close to stack error!!");
	}
	return;
}

///////////////////////////////////////////////
/// get a port that unique at local scope
/// return:
///		port: the local unique port
///		-1: error, will not occur	
///////////////////////////////////////////////
int TransContentPortMgr::getAPortLocal(){
	int tempPort = TransContentSetting::getRandomInt();
	while(1){
		if(isPortExist(tempPort) == E_TRANC_PortNotExist){
			return tempPort;
		}
		tempPort = TransContentSetting::getRandomInt();
	}
	return -1;
}

//////////////////////////////////////////////////////////////////////////
/// remove all port record in portlist
/// each instance of the port should be destroy;
/// not free portList itself in the method
/////////////////////////////////////////////////////////////////////////
void TransContentPortMgr::destroyAllPortRecord(){
	pthread_mutex_lock(&mutex_port);
	for(int i=0; i< mPortCount; ++i){
		if(portList[i].localPort != 0){
			portList[i].localPort = 0;
			delete portList[i].instance;
		}
	}
	pthread_mutex_unlock(&mutex_port);
}


//////////////////////////////////////////////////////////////////////////////
/// check port in port list can be use as record
///
/// parameters:
//		port: look for port
//
//	return:
//		0: port's state can not be changed to record 
//		1: port's state can be changed to record
int TransContentPortMgr::canChangePortStateToRecord(int port){
	int state = PORT_STATE_ERROR;
	debug_enter();
	for(int i=0, count=0; i< mPortCapacity && count < mPortCount; ++i){
		if(portList[i].localPort != 0){
			++count;
			if(portList[i].localPort == port){
				/// check state
				state = portList[i].portState;
				if(state == PORT_STATE_REGISTING || state == PORT_STATE_LISTEN || state == PORT_STATE_ACCEPTING || state == PORT_STATE_ACCEPT_FULL || state == PORT_STATE_CONNECTING || state == PORT_STATE_CONNECTED || state == PORT_STATE_STREAM || state == PORT_STATE_CLOSING){
					return 0;
				}
			}
		}
	}
	return 1;
}
}

////////////////////////////////////////////////////////////////////////
/// close a port
///
/// parameter:
///		port: close the port
///
/// return:
///		E_TRANC_SUCESS: always return this value
////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::closePort(int port){
	closePortToStack(port);
	return removePortRecord(port, -1);
}

///////////////////////////////////////////////////////////////////////////
/// close the port list index record
///
/// parameters:
///		vid: the vroute index
///
/// return:
///		E_TRANC_SUCESS: always return this value
//////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::closeVid(vroute_t vid){
	int port;
	if( vid < 0 || vid > this->mPortCapacity){
		log_error("listen method parameter, vid=%d, out of range", vid);
		return E_TRANC_ParamError;      
	}
	port = portList[vid].localPort;
	if(port <= 0){
		log_error("the vid port:%d out of range", port);
		return E_TRANC_ParamError;
	}
	removePortRecord(-1, vid);
	if(isPortExist(port) == E_TRANC_PortNotExist){
		closePortToStack(port);
	}
	return E_TRANC_SUCESS;
}

///////////////////////////////////////////////////////////////////////////////////
/// inner regist port
///		regist port to stack use give style and return give type
///
/// parameters:
///		port: regist the port to stack
///		portType: regist type(apply, get, check)
///		returnType: return type(vid, port, bool)
///	return:
///		intvalue: the return allow the third parameter set
///		E_TRANC_BufferTooSmall: there no more buffer to hold informaton
////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::registPortInner(int port, int portType, int returnType){
	int index;
	portElement _tempRecord;

	TransContentPortRegist* registInstance = NULL;

	debug_enter();

	/// set values
	_tempRecord.localPort = port;
	_tempRecord.portState = PORT_STATE_REGISTING;
	_tempRecord.romoveCallback = NULL;
	_tempRecord.instance = new TransContentPortRegist();

	/// add to port list
	index = AddPortRecord(&_tempRecord);
	if(index == E_TRANC_BufferTooSmall){
		logd_error("add port to port manager failed, now destroy current created instance!!");
		delete _tempRecord.instance;
		///add port failed, normally because of the buffer is full.
		return E_TRANC_BufferTooSmall;
	}    

	///set parameter of the instance
	registInstance = (TransContentPortRegist*)_tempRecord.instance;
	registInstance->setRegistingPort(port);
	registInstance->setRegistingType(portType);
	registInstance->setAlreadyRegistedPort(getRegistedPort());
	registInstance->setVid(index);
	registInstance->setReturnType(returnType);

	logd_info("call regist port instance to bind a port");
	return registInstance->regist();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
/// test the port state can be chagne to regesit, may be used by bind to check port may be used as stream port later
///
/// parameters:
///		port: the check port
///
///	return:
///		1: port's state can be change to registed
///		0: port's state can not be changed to registed
////////////////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::canChagnePortStateToRegisted(int port){
	int state = PORT_STATE_ERROR;
	debug_enter();
	for(int i=0, count=0; i< mPortCapacity && count < mPortCount; ++i){
		if(portList[i].localPort != 0){
			++count;
			if(portList[i].localPort == port){
				/// check state
				state = portList[i].portState;
				if(state == PORT_STATE_REGISTING || state == PORT_STATE_LISTEN || state == PORT_STATE_ACCEPTING || state == PORT_STATE_ACCEPT_FULL || state == PORT_STATE_CONNECTING || state == PORT_STATE_CONNECTED || state == PORT_STATE_STREAM || state == PORT_STATE_PACKET || state == PORT_STATE_CLOSING){
					return 0;
				}
			}
		}
	}
	return 1;
}

int TransContentPortMgr::canPortStateChangedToFunctionRelate(int port){
	int state = PORT_STATE_ERROR;
	debug_enter();
	for(int i=0, count=0; i< mPortCapacity && count < mPortCount; ++i){
		if(portList[i].localPort != 0){
			++count;
			if(portList[i].localPort == port){
				/// check state
				state = portList[i].portState;
				if(state == PORT_STATE_ERROR || state == PORT_STATE_REGISTING || state == PORT_STATE_CLOSING){
					return 0;
				}
			}
		}
	}
	return 1;
}

//////////////////////////////////////////////////////////////////
/// action for the response result, and show whether dispatcher to next port record again
///
/// parameter:
///		result: the value by dispatcher instance
///		bufferIndex: the buffer contine message, in the index in memory pool
///		recordIndex: the index of the record in port list
///
/// return:
///		1: will not dispatcher to next port record
///		0: will pass to next port record to deal again
///////////////////////////////////////////////////////////////////
int TransContentPortMgr::analysePortResult(int result, int bufferIndex, int recordIndex){
	int result = 1;
	int tempPort = 0;
	ConnectPeer mPeer;
	debug_enter();
	logd_info("analyse the port result: %d", result);
	switch(result){
		case RESPONSE_RESULT_DELETE_RECORD:
			logd_info("analyse port result, the result is delete the port record");
			removePortRecord(-1, recordIndex);
			break;
		case RESPONSE_RESULT_CHANGE_STATE:
			logd_info("analyse port result, the result is should change the port state");
			portList[recordIndex].portState = portList[recordIndex].instance->getNextState();
			break;
		case RESPONSE_RESULT_NOACTION:
			logd_info("analyse port result, the result is no action");
			break;
		case RESPONSE_RESULT_CREATE_STREAM_C:
			logd_info("analyse port rseult, the result is create stream by connect, so create a port stream record and send sync protocol, then return the sucess or failed");
			mPeer = ((TransContentConnect*)portList[recordIndex])->getPeerInfo();
			result = createPortStreamInstance(&mPeer, ((TransContentConnect*)portList[recordIndex])->getRemoteBufferSize(), ((TransContentConnect*)portList[recordIndex])->getRemoteStreamStart, -1);
			if(result == -1){
				logd_error("analyse port result, failed");
			}
			((TransContentConnect*)portList[recordIndex])->setVid(result);
			((TransContentConnect*)portList[recordIndex])->connectFinishe();
			break;
		case RESPONSE_RESULT_CREATE_STREAM_A:
			logd_info("analyse port result, create stream port record by accept");
			 mPeer = ((TransContentConnect*)portList[recordIndex])->getPeerInfo();
			 tempPort = mPeer.localPort;
			 mPeer.localPort = getAPort();

			 logd_info("analyse port result, after create a local port, now start to create a stream port");
			 result = createPortStreamInstance(&mPeer, STREAM_BUFFER_SIZE_DEFAULT, 0, tempPort);
			 if(result == -1){
				 logd_error("analyse port result, create port stream record by accept failed");
			 }
			 setStreamVid(result);
			 logd_info("analyse port result, finished");
			break;
		case RESPONSE_RESULT_RESET_DEFAULT:
			logd_info("analyse port result, reset the port reocrd to default: registed");
			if(portList[recordIndex].instance != NULL){
				delete portList[recordIndex].instance;
				portList[recordIndex].instance = NULL;
			}
				portList[recordIndex].portState = PORT_STATE_REGISTED;
			break;
		case RESPONSE_RESULT_POST_CONITNUE:
			logd_info("analyse port rseult, the message should dispatcher continue");
			result = 0;
			break;
		case RESPONSE_RESULT_RELEASEBUFFER:
			logd_info("analyse port result, the instance set to release the buffer reocrd");
			TransContentMemory::getInstance()->releaseBuffer(bufferIndex);
			break;
		default:
			logd_error("analysePort result, no insance to deal the message, so continue dispatcher to next");
			result = 0;
	}
	debug_leave();
	return result;;
}

////////////////////////////////////////////////////////////////////
/// the port manager deal the main code
///		now just support the heart beat, and the get stack info main message
///	
///		heart beat response and just get stack info
///
///	parameter:
///		content: the content hold the datas
///		index: the buffer in memory offset
///
///	return:
///		1: message dispatcher finished, do not pass it again
///		0: message dispatcher continue, need to pass to next layer, now to instance response
/////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::dispatcherForPortList(char* content, int index){
	int mainCode = content[0];
	int subCode = content[1];
	int result = 1;
	debug_enter();
	switch(mainCode){
		case message_type_heatBeat:
			logd_info("dispatcher for port list, main message is heart beat");
			result = heartBeatResponse(content, index);
			break;
		case message_type_inner_getStackInfo:
			logd_info("dispatcher for port list, main message is get stack info");
			result = TransContentGetStackInfo::response(content, index);
			break;
		default:

	}
	debug_leave();
	return result;
}

////////////////////////////////////////////////////////////////////////////////////////////
/// call the port record instance to deal the content
///		call instance to deal the main message
///
///	parameter:
///		content: the buffer contine the message
///		index: the buffer index in memory pool
///
///	return:
///		1: message dispathcer finished, do not pass it again
///		0: message dispatcher continue, need to passed to next layer.
////////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::dispatcherForPortInstance(char* content, int index, int portRecordInstanceIndex){
	int reuslt = 0;
	transContentIDispResponse* ins = portList[portRecordInstanceIndex].instance;
	debug_enter();
	result = ins->dispatcher(content, index);
	logd_error("dispatcher for port instance, the instance result = %d, start analyse the result", result);
	result = analysePortResult(result, index, portRecordInstanceIndex);
	logd_error("dispatcher for port instance, result is: %d", result);
	debug_leave();
	return result;
}

///////////////////////////////////////////////////////////////////////////////
/// deal the message for not support ones
///
/// parameter:
///		content: the buffer contine the message
///		index: the buffer index in memory pool
///	return:
///		E_TRANC_NOT_SUPPORT_MAINCODE: not support the main message
///////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::dispatcherForException(char* content, int index){
	debug_enter();
	logd_error("dispatcher for exception, the message not support, now delete the port record");
	TransContentMemory::getInstance()->releaseBuffer(index);
	debug_leave();
	return E_TRANC_NOT_SUPPORT_MAINCODE;
}


///////////////////////////////////////////////////////////////////////////////////////
/// create a port stream record with received remote device info
///		if the instance should get by connect, set the acceptPort to -1
///		after create the stream port record, should init sync the port record with remote
///
/// parameter:
///		peer: remote device information
///		remoteBufferSize: remote device stream port record buffer size
///		remoteStreamStart: remote device stream port stream value start
///		acceptPort: the accept port for the stream
///
///	return:
///		index: the port stream index, when sucess
///		-1: when error
//////////////////////////////////////////////////////////////////////////////////////////////////
int TransContentPortMgr::createPortStreamInstance(const ConnectPeer* peer, int remoteBufferSize, int remoteStreamStart, int acceptPort){
	ConnectPeer _innerPeer = *peer;
	portElement element;
	int index;
	debug_enter();
	TransContentPortStream* instance = new TransContentPortStream(peer);
	instance->setRemoteStreamStart(remoteStreamStart);
	instance->setAcceptPort(acceptPort);
	instance->setRemoteBufferSize(remoteBufferSize);
	element.localPort = _innserPeer->localPort;
	element.portState = PORT_STATE_STREAM;
	element.romoveCallback = NULL;
	element.instnace = instance;
	
	/// add port record
	index = AddPortRecord(&element);
	logd_info("create port stream record, the result is: %d", index);

	/// wait for stream ack
	if(instace->init_sync() == 0){
		logd_error("create port instance error, init sync with remote device failed");
		return -1;
	}
	
	/// init with remote device finished
	return index;
}

/////////////////////////////////////////////////////////////////////////
/// init the client info
///		first regist a port, this port is used for inner, that can you it later in regist
///		then get stack info, local address
int TransContentPortMgr::initClient(){
	int port = 0;
	debug_enter();
	port = getAPort();
	addPortRecordAsRegist(port);
	TransContentGetStackInfo::getStackLocalAddr();	
	debug_leave();
}
